﻿#include "stdafx.h"
#include "Mesh.h"
#include <iostream>

#define _USE_MATH_DEFINES
#include <math.h>

#define	COLORNUM		15

using namespace std;

float	ColorArr[COLORNUM][3] = { { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 },
{ 1.0, 1.0, 0.0 }, { 1.0, 0.0, 1.0 }, { 0.0, 1.0, 1.0 },
{ 0.3, 0.3, 0.3 }, { 0.5, 0.5, 0.5 }, { 0.9, 0.9, 0.9 },
{ 1.0, 0.5, 0.5 }, { 0.5, 1.0, 0.5 }, { 0.5, 0.5, 1.0 },
{ 0.0, 0.0, 0.0 }, { 0.2, 0.2, 0.2 }, { 1.0, 1.0, 1.0 } };

void Mesh::CreateXZPlane(int row, int col, float size){
	numVerts = (row + 1)*(col + 1);
	numFaces = row*col;
	pt = new Point3[numVerts];
	face = new Face[numFaces];

	float x, y, z;
	x = -(float)row*size / 2;
	y = 0;
	z = -(float)col*size / 2;

	//Tính toán và cập nhập các điểm
	int i = 0;
	for (int r = 0; r < row + 1; r++){
		for (int c = 0; c < col + 1; c++) {
			pt[i].set(x, y, z);

			/*Test các điểm
			cout << "i = " << i;
			cout << ", x = " << x;
			cout << ", y = " << y;
			cout << ", z = " << z << endl;
			*/

			x += size; //tăng toạ độ x
			i++;
		}
		//reset toạ độ x và tăng toạ độ z
		x = -(float)row * size / 2;
		z += size;
	}

	//Tính toán và cập nhập các mặt
	//Các mặt quay lên, nên các điểm sẽ được xếp clockwise
	i = 0;
	int a = 0, b = 0;
	for (int r = 0; r < row; r++) {
		for (int c = 0; c < col; c++){
			face[i].nVerts = 4;
			face[i].vert = new VertexID[4];
			for (int j = 0; j < 4; j++) {
				a = (-j*j + 3 * j) / 2;
				b = (j < 2) ? 0 : 1;

				/*cout << "face[" << i << "]";
				cout << ".vert[" << j << "].vertIndex = " << (c + a) + (r + b)*(col + 1) << endl;*/

				face[i].vert[j].vertIndex = (c + a) + (r + b)*(col + 1);
				face[i].vert[j].colorIndex = ((i + r) % 2 == 0) ? 12 : 14;
			}
			i++;
		}
	}
}

void Mesh::CreateCube(float	fSize)
{

	int col, row, dep;
	col = row = dep = 1;

	numVerts = (col + 1)*(row + 1)*(dep + 1);
	pt = new Point3[numVerts];
	numFaces = col*row*dep * 6; //col*row*dep*6
	face = new Face[numFaces];

	float x, y, z;
	x = -(float)col*fSize / 2.0f;
	y = (float)dep*fSize;
	z = -(float)row*fSize / 2.0f;

	int i = 0;
	for (int d = 0; d < dep + 1; d++) {
		for (int r = 0; r < row + 1; r++) {
			for (int c = 0; c < col + 1; c++) {
				pt[i].set(x, y, z);
				x += fSize;
				i++;
			}
			x = -(float)col*fSize / 2.0f;
			z += fSize;
		}
		x = -(float)col*fSize / 2.0f;
		z = -(float)row*fSize / 2.0f;
		y -= fSize;
	}

	i = 0;
	for (int d = 0; d < dep; d++) {
		for (int r = 0; r < row; r++) {
			for (int c = 0; c < col; c++) {

				//TOP
				face[i].nVerts = 4;
				face[i].vert = new VertexID[4];
				face[i].vert[0].vertIndex = c + 0 + r*(col + 1) + d*(row + 1)*(col + 1);
				face[i].vert[1].vertIndex = c + 1 + r*(col + 1) + d*(row + 1)*(col + 1);
				face[i].vert[2].vertIndex = c + 1 + (r + 1)*(col + 1) + d*(row + 1)*(col + 1);
				face[i].vert[3].vertIndex = c + 0 + (r + 1)*(col + 1) + d*(row + 1)*(col + 1);
				for (int j = 0; j < 4; j++) {
					face[i].vert[j].colorIndex = i;
				}
				i++;

				//BOTTOM
				face[i].nVerts = 4;
				face[i].vert = new VertexID[4];
				face[i].vert[3].vertIndex = c + 0 + r*(col + 1) + (d + 1)*(row + 1)*(col + 1);
				face[i].vert[2].vertIndex = c + 1 + r*(col + 1) + (d + 1)*(row + 1)*(col + 1);
				face[i].vert[1].vertIndex = c + 1 + (r + 1)*(col + 1) + (d + 1)*(row + 1)*(col + 1);
				face[i].vert[0].vertIndex = c + 0 + (r + 1)*(col + 1) + (d + 1)*(row + 1)*(col + 1);
				for (int j = 0; j < 4; j++) {
					face[i].vert[j].colorIndex = i;
				}
				i++;

				//LEFT
				face[i].nVerts = 4;
				face[i].vert = new VertexID[4];
				face[i].vert[0].vertIndex = c + r*(col + 1) + d*(row + 1)*(col + 1);
				face[i].vert[1].vertIndex = c + (r + 1)*(col + 1) + d*(row + 1)*(col + 1);
				face[i].vert[2].vertIndex = c + (r + 1)*(col + 1) + (d + 1)*(row + 1)*(col + 1);
				face[i].vert[3].vertIndex = c + r*(col + 1) + (d + 1)*(row + 1)*(col + 1);
				for (int j = 0; j < 4; j++) {
					face[i].vert[j].colorIndex = i;
				}
				i++;

				//RIGHT
				face[i].nVerts = 4;
				face[i].vert = new VertexID[4];
				face[i].vert[3].vertIndex = c + 1 + r*(col + 1) + d*(row + 1)*(col + 1);
				face[i].vert[2].vertIndex = c + 1 + (r + 1)*(col + 1) + d*(row + 1)*(col + 1);
				face[i].vert[1].vertIndex = c + 1 + (r + 1)*(col + 1) + (d + 1)*(row + 1)*(col + 1);
				face[i].vert[0].vertIndex = c + 1 + r*(col + 1) + (d + 1)*(row + 1)*(col + 1);
				for (int j = 0; j < 4; j++) {
					face[i].vert[j].colorIndex = i;
				}
				i++;

				//NEAR
				face[i].nVerts = 4;
				face[i].vert = new VertexID[4];
				face[i].vert[0].vertIndex = c + 0 + r*(col + 1) + d*(row + 1)*(col + 1);
				face[i].vert[1].vertIndex = c + 1 + r*(col + 1) + d*(row + 1)*(col + 1);
				face[i].vert[2].vertIndex = c + 1 + r*(col + 1) + (d + 1)*(row + 1)*(col + 1);
				face[i].vert[3].vertIndex = c + 0 + r*(col + 1) + (d + 1)*(row + 1)*(col + 1);
				for (int j = 0; j < 4; j++) {
					face[i].vert[j].colorIndex = i;
				}
				i++;

				//FAR
				face[i].nVerts = 4;
				face[i].vert = new VertexID[4];
				face[i].vert[3].vertIndex = c + 0 + (r + 1)*(col + 1) + d*(row + 1)*(col + 1);
				face[i].vert[2].vertIndex = c + 1 + (r + 1)*(col + 1) + d*(row + 1)*(col + 1);
				face[i].vert[1].vertIndex = c + 1 + (r + 1)*(col + 1) + (d + 1)*(row + 1)*(col + 1);
				face[i].vert[0].vertIndex = c + 0 + (r + 1)*(col + 1) + (d + 1)*(row + 1)*(col + 1);
				for (int j = 0; j < 4; j++) {
					face[i].vert[j].colorIndex = i;
				}
				i++;

			}
		}
	}

}

void Mesh::CreateSphere(int nSlices, int nStacks, GLdouble fRadius) {
	// Stack : múi cắt dọc
	// Slice : lát cắt ngang (có thể tìm hình minh hoạ trên google "slice sphere")
	numVerts = nSlices * (nStacks - 1) + 2;
	pt = new Point3[numVerts];
	float theta = M_PI / (float)nStacks;
	float phi = 2 * M_PI / (float)nSlices;
	int v = 0;

	float x0, y0, z0;
	x0 = z0 = 0;
	y0 = 0;

	for (int i = 1; i < nStacks; i++){
		for (int j = 0; j < nSlices; j++){
			pt[v].set(
				x0 + fRadius*cosf(j*phi)*sinf(i*theta), //R*cos => x
				y0 + fRadius*sinf(j*phi)*sinf(i*theta), //R*sin => y
				z0 + fRadius*cosf(i*theta)); //tăng lên qua từng Stack
			/*
			cout << v << " : " << pt[v].x << " " << pt[v].y << " " << pt[v].z << endl;
			*/
			v++;
		}
	}

	pt[v].set(x0, y0, z0 + fRadius); v++;
	pt[v].set(x0, y0, z0 - fRadius);

	numFaces = nSlices * nStacks;
	face = new Face[numFaces];

	for (int k = 0; k < nStacks - 2; k++){
		for (int i = 0; i < nSlices; i++){
			face[k*nSlices + i].nVerts = 4;
			face[k*nSlices + i].vert = new VertexID[face[k*nSlices + i].nVerts];

			face[k*nSlices + i].vert[0].vertIndex = k*nSlices + i;
			face[k*nSlices + i].vert[1].vertIndex = k*nSlices + (i + 1) % nSlices;
			face[k*nSlices + i].vert[2].vertIndex = (k + 1) % (nStacks)*nSlices + (i + 1) % nSlices;
			face[k*nSlices + i].vert[3].vertIndex = (k + 1) % (nStacks)*nSlices + i;

			for (int j = 0; j < face[k*nSlices + i].nVerts; j++)
				face[k*nSlices + i].vert[j].colorIndex = k*nSlices + i;
		}
	}

	// nSlices đỉnh đầu nối với đỉnh đầu
	int k;
	k = nStacks - 2;
	for (int i = 0; i < nSlices; i++) {
		face[k*nSlices + i].nVerts = 3;

		face[k*nSlices + i].vert = new VertexID[face[k*nSlices + i].nVerts];

		face[k*nSlices + i].vert[2].vertIndex = v - 1;
		face[k*nSlices + i].vert[1].vertIndex = i;
		face[k*nSlices + i].vert[0].vertIndex = (i + 1) % nSlices;

		for (int j = 0; j < face[k*nSlices + i].nVerts; j++)
			face[k*nSlices + i].vert[j].colorIndex = k*nSlices + i;
	}
	// nSlices đỉnh cuối nối với đỉnh cuối
	k = nStacks - 1;
	for (int i = 0; i < nSlices; i++) {
		face[k*nSlices + i].nVerts = 3;

		face[k*nSlices + i].vert = new VertexID[face[k*nSlices + i].nVerts];

		face[k*nSlices + i].vert[0].vertIndex = v;
		face[k*nSlices + i].vert[1].vertIndex = (k - 1)*nSlices + i;
		face[k*nSlices + i].vert[2].vertIndex = (k - 1)*nSlices + (i + 1) % nSlices;

		for (int j = 0; j < face[k*nSlices + i].nVerts; j++)
			face[k*nSlices + i].vert[j].colorIndex = k*nSlices + i;
	}
}

void Mesh::CreateTruncatedCube(float fSize)
{
	numVerts = 24; //8*3
	pt = new Point3[numVerts];
	numFaces = 14; //6 + 8
	face = new Face[numFaces];

	float x, y, z;
	x = -fSize / 2.0;
	y = fSize;
	z = -fSize / 2.0 + fSize / 3.0;

	float phi = -M_PI + M_PI / 8.0;

	for (int i = 0; i < 8; i++) {
		pt[i].set(x, y, z);
		pt[i + 16].set(x, 0, z);
		phi += M_PI / 4.0;
		x = fSize / 2.0*cosf(phi);
		z = fSize / 2.0*sinf(phi);
	}

	x = -fSize / 2.0; y -= fSize / 3.0; z = -fSize / 2.0;
	pt[8].set(x, y, z); x += fSize;
	pt[9].set(x, y, z); z += fSize;
	pt[10].set(x, y, z); x -= fSize;
	pt[11].set(x, y, z); x = -fSize / 2.0; y -= fSize / 3.0; z = -fSize / 2.0;
	pt[12].set(x, y, z); x += fSize;
	pt[13].set(x, y, z); z += fSize;
	pt[14].set(x, y, z); x -= fSize;
	pt[15].set(x, y, z); x = -fSize / 2.0; y -= fSize / 3.0; z = -fSize / 2.0 + fSize / 3.0;

	//TOP -- BOTTOM
	face[0].nVerts = 8;
	face[0].vert = new VertexID[8];
	face[1].nVerts = 8;
	face[1].vert = new VertexID[8];
	for (int i = 0; i < 8; i++) {
		face[0].vert[i].vertIndex = i;
		face[1].vert[7 - i].vertIndex = i + 16;
	}

	//LEFT
	face[2].nVerts = 8;
	face[2].vert = new VertexID[8];
	face[2].vert[0].vertIndex = 7;
	face[2].vert[1].vertIndex = 11;
	face[2].vert[2].vertIndex = 15;
	face[2].vert[3].vertIndex = 23;
	face[2].vert[4].vertIndex = 16;
	face[2].vert[5].vertIndex = 12;
	face[2].vert[6].vertIndex = 8;
	face[2].vert[7].vertIndex = 0;

	//RIGHT
	face[3].nVerts = 8;
	face[3].vert = new VertexID[8];
	face[3].vert[0].vertIndex = 3;
	face[3].vert[1].vertIndex = 9;
	face[3].vert[2].vertIndex = 13;
	face[3].vert[3].vertIndex = 19;
	face[3].vert[4].vertIndex = 20;
	face[3].vert[5].vertIndex = 14;
	face[3].vert[6].vertIndex = 10;
	face[3].vert[7].vertIndex = 4;

	//NEAR
	face[4].nVerts = 8;
	face[4].vert = new VertexID[8];
	face[4].vert[0].vertIndex = 5;
	face[4].vert[1].vertIndex = 10;
	face[4].vert[2].vertIndex = 14;
	face[4].vert[3].vertIndex = 21;
	face[4].vert[4].vertIndex = 22;
	face[4].vert[5].vertIndex = 15;
	face[4].vert[6].vertIndex = 11;
	face[4].vert[7].vertIndex = 6;

	//FAR
	face[5].nVerts = 8;
	face[5].vert = new VertexID[8];
	face[5].vert[7].vertIndex = 2;
	face[5].vert[6].vertIndex = 9;
	face[5].vert[5].vertIndex = 13;
	face[5].vert[4].vertIndex = 18;
	face[5].vert[3].vertIndex = 17;
	face[5].vert[2].vertIndex = 12;
	face[5].vert[1].vertIndex = 8;
	face[5].vert[0].vertIndex = 1;

	for (int i = 0; i <= 5; i++) {
		for (int j = 0; j < 8; j++) {
			face[i].vert[j].colorIndex = i;
		}
	}

	//06
	face[6].nVerts = 3;
	face[6].vert = new VertexID[3];
	face[6].vert[2].vertIndex = 0;
	face[6].vert[1].vertIndex = 1;
	face[6].vert[0].vertIndex = 8;

	//07
	face[7].nVerts = 3;
	face[7].vert = new VertexID[3];
	face[7].vert[0].vertIndex = 3;
	face[7].vert[1].vertIndex = 2;
	face[7].vert[2].vertIndex = 9;

	//08
	face[8].nVerts = 3;
	face[8].vert = new VertexID[3];
	face[8].vert[0].vertIndex = 5;
	face[8].vert[1].vertIndex = 4;
	face[8].vert[2].vertIndex = 10;

	//09
	face[9].nVerts = 3;
	face[9].vert = new VertexID[3];
	face[9].vert[0].vertIndex = 7;
	face[9].vert[1].vertIndex = 6;
	face[9].vert[2].vertIndex = 11;

	//10
	face[10].nVerts = 3;
	face[10].vert = new VertexID[3];
	face[10].vert[2].vertIndex = 12;
	face[10].vert[1].vertIndex = 17;
	face[10].vert[0].vertIndex = 16;

	//11
	face[11].nVerts = 3;
	face[11].vert = new VertexID[3];
	face[11].vert[0].vertIndex = 13;
	face[11].vert[1].vertIndex = 18;
	face[11].vert[2].vertIndex = 19;

	//12
	face[12].nVerts = 3;
	face[12].vert = new VertexID[3];
	face[12].vert[0].vertIndex = 14;
	face[12].vert[1].vertIndex = 20;
	face[12].vert[2].vertIndex = 21;

	//13
	face[13].nVerts = 3;
	face[13].vert = new VertexID[3];
	face[13].vert[0].vertIndex = 15;
	face[13].vert[1].vertIndex = 22;
	face[13].vert[2].vertIndex = 23;

	for (int i = 6; i <= 13; i++){
		for (int j = 0; j < 3; j++) {
			face[i].vert[j].colorIndex = i;
		}
	}
}

void Mesh::CreateDodecahedron(float fSize){
	numVerts = 8 + 4*3;
	pt = new Point3[numVerts];
	numFaces = 12;
	face = new Face[numFaces];

	float phi = (1.0 + sqrt(5.0)) / 2.0;
	float unit = 1.0;

	float x, y, z;
	
	//blue
	z = 0;
	x = -unit / phi;	y = phi;	pt[0].set(x, y, z);
	x = unit / phi;		y = phi;	pt[1].set(x, y, z);
	x = -unit / phi;	y = -phi;	pt[18].set(x, y, z);
	x = unit / phi;		y = -phi;	pt[19].set(x, y, z);

	//cube

	x = -unit;	y = unit;	z = -unit;	pt[2].set(x, y, z);
	x = unit;	y = unit;	z = -unit;	pt[3].set(x, y, z);
	x = unit;	y = unit;	z = unit;	pt[4].set(x, y, z);
	x = -unit;	y = unit;	z = unit;	pt[5].set(x, y, z);
	x = -unit;	y = -unit;	z = -unit;	pt[14].set(x, y, z);
	x = unit;	y = -unit;	z = -unit;	pt[15].set(x, y, z);
	x = unit;	y = -unit;	z = unit;	pt[16].set(x, y, z);
	x = -unit;	y = -unit;	z = unit;	pt[17].set(x, y, z);

	//green
	x = 0;
	y = unit / phi;		z = -phi;	pt[6].set(x, y, z);
	y = unit / phi;		z = phi;	pt[7].set(x, y, z);
	y = -unit / phi;	z = -phi;	pt[12].set(x, y, z);
	y = -unit / phi;	z = phi;	pt[13].set(x, y, z);

	//pink
	y = 0;
	x = -phi;	z = -unit / phi;	pt[8].set(x, y, z);
	x = phi;	z = -unit / phi;	pt[9].set(x, y, z);
	x = phi;	z = unit / phi;		pt[10].set(x, y, z);
	x = -phi;	z = unit / phi;		pt[11].set(x, y, z);

	for (int i = 0; i < 12; i++){
		face[i].nVerts = 5;
		face[i].vert = new VertexID[5];
	}

	//face blue up
	face[0].vert[4].vertIndex = 0;
	face[0].vert[3].vertIndex = 2;
	face[0].vert[2].vertIndex = 8;
	face[0].vert[1].vertIndex = 11;
	face[0].vert[0].vertIndex = 5;

	face[1].vert[4].vertIndex = 0;
	face[1].vert[3].vertIndex = 1;
	face[1].vert[2].vertIndex = 3;
	face[1].vert[1].vertIndex = 6;
	face[1].vert[0].vertIndex = 2;

	face[2].vert[0].vertIndex = 1;
	face[2].vert[1].vertIndex = 3;
	face[2].vert[2].vertIndex = 9;
	face[2].vert[3].vertIndex = 10;
	face[2].vert[4].vertIndex = 4;

	face[3].vert[0].vertIndex = 0;
	face[3].vert[1].vertIndex = 1;
	face[3].vert[2].vertIndex = 4;
	face[3].vert[3].vertIndex = 7;
	face[3].vert[4].vertIndex = 5;

	//face not blue
	face[4].vert[4].vertIndex = 2;
	face[4].vert[3].vertIndex = 6;
	face[4].vert[2].vertIndex = 12;
	face[4].vert[1].vertIndex = 14;
	face[4].vert[0].vertIndex = 8;

	face[5].vert[4].vertIndex = 3;
	face[5].vert[3].vertIndex = 9;
	face[5].vert[2].vertIndex = 15;
	face[5].vert[1].vertIndex = 12;
	face[5].vert[0].vertIndex = 6;

	face[6].vert[0].vertIndex = 4;
	face[6].vert[1].vertIndex = 10;
	face[6].vert[2].vertIndex = 16;
	face[6].vert[3].vertIndex = 13;
	face[6].vert[4].vertIndex = 7;

	face[7].vert[0].vertIndex = 5;
	face[7].vert[1].vertIndex = 7;
	face[7].vert[2].vertIndex = 13;
	face[7].vert[3].vertIndex = 17;
	face[7].vert[4].vertIndex = 11;

	//face blue down
	face[8].vert[4].vertIndex = 8;
	face[8].vert[3].vertIndex = 14;
	face[8].vert[2].vertIndex = 18;
	face[8].vert[1].vertIndex = 17;
	face[8].vert[0].vertIndex = 11;

	face[9].vert[4].vertIndex = 12;
	face[9].vert[3].vertIndex = 15;
	face[9].vert[2].vertIndex = 19;
	face[9].vert[1].vertIndex = 18;
	face[9].vert[0].vertIndex = 14;

	face[10].vert[0].vertIndex = 9;
	face[10].vert[1].vertIndex = 15;
	face[10].vert[2].vertIndex = 19;
	face[10].vert[3].vertIndex = 16;
	face[10].vert[4].vertIndex = 10;

	face[11].vert[0].vertIndex = 13;
	face[11].vert[1].vertIndex = 16;
	face[11].vert[2].vertIndex = 19;
	face[11].vert[3].vertIndex = 18;
	face[11].vert[4].vertIndex = 17;

	for (int i = 0; i < 12; i++){
		for (int j = 0; j < 5; j++) {
			face[i].vert[j].colorIndex = i;
		}
	}
}

void Mesh::CreateIcosahedron(float fSize){
	double X = .525731112119133606;
	double Z = .850650808352039932;
	static GLfloat vdata[12][3] = {
		{ -X, 0.0, Z }, { X, 0.0, Z }, { -X, 0.0, -Z }, { X, 0.0, -Z },
		{ 0.0, Z, X }, { 0.0, Z, -X }, { 0.0, -Z, X }, { 0.0, -Z, -X },
		{ Z, X, 0.0 }, { -Z, X, 0.0 }, { Z, -X, 0.0 }, { -Z, -X, 0.0 }
	};
	static GLuint tindices[20][3] = {
		{ 0, 4, 1 }, { 0, 9, 4 }, { 9, 5, 4 }, { 4, 5, 8 }, { 4, 8, 1 },
		{ 8, 10, 1 }, { 8, 3, 10 }, { 5, 3, 8 }, { 5, 2, 3 }, { 2, 7, 3 },
		{ 7, 10, 3 }, { 7, 6, 10 }, { 7, 11, 6 }, { 11, 0, 6 }, { 0, 1, 6 },
		{ 6, 1, 10 }, { 9, 0, 11 }, { 9, 11, 2 }, { 9, 2, 5 }, { 7, 2, 11 } };

	numVerts = 12;
	pt = new Point3[numVerts];
	numFaces = 20;
	face = new Face[numFaces];

	for (int i = 0; i < 12; i++) {
		pt[i].set(vdata[i][0], vdata[i][1], vdata[i][2]);
	}
	for (int i = 0; i < 20; i++) {
		face[i].nVerts = 3;
		face[i].vert = new VertexID[3];
		for (int j = 0; j < 3;j++){
			face[i].vert[j].vertIndex = tindices[i][j];
			face[i].vert[j].colorIndex = i;
		}
	}
}

void Mesh::CreateCylinder(int nSegments, float fHeight, float fRadius){
	numVerts = nSegments * 2 + 2; //number of vertexes
	pt = new Point3[numVerts];

	float theta = 2 * M_PI / float(nSegments);
	float c = cosf(theta);
	float s = sinf(theta);
	float t;

	float z = fRadius;
	float x = 0;
	float y = fHeight;

	pt[2 * nSegments].set(0, y, 0); //Tâm trên
	pt[2 * nSegments + 1].set(0, 0, 0); //Tâm dưới

	for (int i = 0; i < nSegments; i++) {

		// 01 trong 03 công thức biến thể của phương trình đường tròn

		pt[i].set(x, y, z);
		pt[i + nSegments].set(x, 0, z);

		t = z;
		z = c*z - s*x;
		x = s*t + c*x;
	}

	numFaces = nSegments * 3;
	face = new Face[numFaces];

	int m = 0, n = 0;
	for (int i = 0; i < nSegments; i++) {

		/*Vẽ vòng ngoài*/
		face[i].nVerts = 4;
		face[i].vert = new VertexID[face[i].nVerts];
		face[i].vert[0].vertIndex = i;
		face[i].vert[1].vertIndex = (i + 1) % nSegments;
		face[i].vert[2].vertIndex = (i + 1) % nSegments + nSegments;
		face[i].vert[3].vertIndex = nSegments + i;
		for (int j = 0; j < face[i].nVerts; j++)
			face[i].vert[j].colorIndex = i;

		/*Vẽ mặt trên*/
		m = i + nSegments;
		face[m].nVerts = 3;
		face[m].vert = new VertexID[face[m].nVerts];
		face[m].vert[2].vertIndex = nSegments * 2; //Tâm trên
		face[m].vert[1].vertIndex = i;
		face[m].vert[0].vertIndex = (i + 1) % nSegments;
		for (int j = 0; j < face[m].nVerts; j++)
			face[m].vert[j].colorIndex = m;

		/*Vẽ mặt dưới*/
		n = m + nSegments;
		face[n].nVerts = 3;
		face[n].vert = new VertexID[face[n].nVerts];
		face[n].vert[0].vertIndex = nSegments * 2 + 1; //Tâm dưới
		face[n].vert[1].vertIndex = i + nSegments;
		face[n].vert[2].vertIndex = (i + 1) % nSegments + nSegments;
		for (int j = 0; j < face[n].nVerts; j++)
			face[n].vert[j].colorIndex = n;
	}
}

void Mesh::CreateCuboid(float fSizeX, float fSizeY, float fSizeZ) {

	numVerts = 8; //number of vertexes
	pt = new Point3[numVerts];
	pt[0].set(-fSizeX / 2, fSizeY, fSizeZ / 2);
	pt[1].set(fSizeX / 2, fSizeY, fSizeZ / 2);
	pt[2].set(fSizeX / 2, fSizeY, -fSizeZ / 2);
	pt[3].set(-fSizeX / 2, fSizeY, -fSizeZ / 2);
	pt[4].set(-fSizeX / 2, 0, fSizeZ / 2);
	pt[5].set(fSizeX / 2, 0, fSizeZ / 2);
	pt[6].set(fSizeX / 2, 0, -fSizeZ / 2);
	pt[7].set(-fSizeX / 2, 0, -fSizeZ / 2);


	numFaces = 6;
	face = new Face[numFaces];

	for (int i = 0; i < numFaces; i++) {
		face[i].nVerts = 4;
		face[i].vert = new VertexID[face[i].nVerts];
		for (int j = 0; j < face[i].nVerts; j++)
			face[i].vert[j].colorIndex = i;
	}

	//Right face
	face[0].vert[3].vertIndex = 1;
	face[0].vert[2].vertIndex = 5;
	face[0].vert[1].vertIndex = 6;
	face[0].vert[0].vertIndex = 2;

	//Left face
	face[1].vert[3].vertIndex = 0;
	face[1].vert[2].vertIndex = 3;
	face[1].vert[1].vertIndex = 7;
	face[1].vert[0].vertIndex = 4;

	//top face
	face[2].vert[3].vertIndex = 0;
	face[2].vert[2].vertIndex = 1;
	face[2].vert[1].vertIndex = 2;
	face[2].vert[0].vertIndex = 3;

	//bottom face
	face[3].vert[3].vertIndex = 7;
	face[3].vert[2].vertIndex = 6;
	face[3].vert[1].vertIndex = 5;
	face[3].vert[0].vertIndex = 4;

	//near face
	face[4].vert[3].vertIndex = 4;
	face[4].vert[2].vertIndex = 5;
	face[4].vert[1].vertIndex = 1;
	face[4].vert[0].vertIndex = 0;

	//Far face
	face[5].vert[3].vertIndex = 3;
	face[5].vert[2].vertIndex = 2;
	face[5].vert[1].vertIndex = 6;
	face[5].vert[0].vertIndex = 7;
}

void Mesh::CreateUShape(float fSizeX, float fSizeY, float fSizeZ, float fThick){

	numVerts = 20; //number of vertexes
	pt = new Point3[numVerts];

	//
	pt[0].set(-fSizeX/2, fSizeY/2, fSizeZ/2);
	pt[1].set(-fSizeX/2 + fThick, fSizeY/2, fSizeZ/2);
	pt[2].set(-fSizeX/2 + fThick, fSizeY/2, -fSizeZ/2 + fThick);
	pt[3].set(-fSizeX/2, fSizeY/2, -fSizeZ/2 + fThick);

	pt[4].set(-fSizeX/2, -fSizeY/2, fSizeZ/2);
	pt[5].set(-fSizeX/2 + fThick, -fSizeY/2, fSizeZ/2);
	pt[6].set(-fSizeX/2 + fThick, -fSizeY/2, -fSizeZ/2 + fThick);
	pt[7].set(-fSizeX/2, -fSizeY/2, -fSizeZ/2 + fThick);

	pt[8].set(fSizeX/2 - fThick, fSizeY/2, fSizeZ/2);
	pt[9].set(fSizeX/2, fSizeY/2, fSizeZ/2);
	pt[10].set(fSizeX/2, fSizeY/2, -fSizeZ/2 + fThick);
	pt[11].set(fSizeX/2 - fThick, fSizeY/2, -fSizeZ/2 + fThick);

	pt[12].set(fSizeX/2 - fThick, -fSizeY/2, fSizeZ/2);
	pt[13].set(fSizeX/2, -fSizeY/2, fSizeZ/2);
	pt[14].set(fSizeX/2, -fSizeY/2, -fSizeZ/2 + fThick);
	pt[15].set(fSizeX/2 - fThick, -fSizeY/2, -fSizeZ/2 + fThick);

	pt[16].set(fSizeX/2, fSizeY/2, -fSizeZ/2);
	pt[17].set(-fSizeX/2, fSizeY/2, -fSizeZ/2);

	pt[18].set(fSizeX/2, -fSizeY/2, -fSizeZ/2);
	pt[19].set(-fSizeX/2, -fSizeY/2, -fSizeZ/2);

	numFaces = 18;
	face = new Face[numFaces];

	for (int i = 0; i < numFaces; i++) {
		face[i].nVerts = 4;
		face[i].vert = new VertexID[4];
		for (int j = 0; j < face[i].nVerts; j++)
			face[i].vert[j].colorIndex = i;
	}

	//Các điểm trên các mặt left, top, far sắp xếp thuận chiều đồng hồ, các mặt right, bottom, near ngược lại
	//==> Xem sol để có nguyên tắc "tắc"
	//Hệ Oxyz: y hướng lên, x hướng qua phải, z hướng vào trong

	//Left face						//Right face
	face[0].vert[3].vertIndex = 0;	face[1].vert[0].vertIndex = 1;
	face[0].vert[2].vertIndex = 3;	face[1].vert[1].vertIndex = 2;
	face[0].vert[1].vertIndex = 7;	face[1].vert[2].vertIndex = 6;
	face[0].vert[0].vertIndex = 4;	face[1].vert[3].vertIndex = 5;

	//Top face						//Bottom face
	face[2].vert[3].vertIndex = 0;	face[3].vert[0].vertIndex = 4;
	face[2].vert[2].vertIndex = 1;	face[3].vert[1].vertIndex = 5;
	face[2].vert[1].vertIndex = 2;	face[3].vert[2].vertIndex = 6;
	face[2].vert[0].vertIndex = 3;	face[3].vert[3].vertIndex = 7;

	//Near face						//Far face
	face[4].vert[0].vertIndex = 0;	face[5].vert[3].vertIndex = 2;
	face[4].vert[1].vertIndex = 1;	face[5].vert[2].vertIndex = 3;
	face[4].vert[2].vertIndex = 5;	face[5].vert[1].vertIndex = 7;
	face[4].vert[3].vertIndex = 4;	face[5].vert[0].vertIndex = 6;

	//02
	//Left face						//Right face
	face[6].vert[3].vertIndex = 8;	face[7].vert[0].vertIndex = 14;
	face[6].vert[2].vertIndex = 11;	face[7].vert[1].vertIndex = 13;
	face[6].vert[1].vertIndex = 15;	face[7].vert[2].vertIndex = 9;
	face[6].vert[0].vertIndex = 12;	face[7].vert[3].vertIndex = 10;

	//Top face						//Bottom face
	face[8].vert[3].vertIndex = 8;	face[9].vert[0].vertIndex = 12;
	face[8].vert[2].vertIndex = 9;	face[9].vert[1].vertIndex = 13;
	face[8].vert[1].vertIndex = 10;	face[9].vert[2].vertIndex = 14;
	face[8].vert[0].vertIndex = 11;	face[9].vert[3].vertIndex = 15;

	//Near face						//Far face
	face[10].vert[0].vertIndex = 8;	 face[11].vert[3].vertIndex = 10;
	face[10].vert[1].vertIndex = 9;	 face[11].vert[2].vertIndex = 11;
	face[10].vert[2].vertIndex = 13; face[11].vert[1].vertIndex = 15;
	face[10].vert[3].vertIndex = 12; face[11].vert[0].vertIndex = 14;

	//03
	//Left face						//Right face
	face[12].vert[3].vertIndex = 3;	face[13].vert[0].vertIndex = 10;
	face[12].vert[2].vertIndex = 17; face[13].vert[1].vertIndex = 16;
	face[12].vert[1].vertIndex = 19; face[13].vert[2].vertIndex = 18;
	face[12].vert[0].vertIndex = 7;	face[13].vert[3].vertIndex = 14;

	//Top face						//Bottom face
	face[14].vert[3].vertIndex = 3;	face[15].vert[0].vertIndex = 7;
	face[14].vert[2].vertIndex = 10; face[15].vert[1].vertIndex = 14;
	face[14].vert[1].vertIndex = 16; face[15].vert[2].vertIndex = 18;
	face[14].vert[0].vertIndex = 17; face[15].vert[3].vertIndex = 19;

	//Near face						//Far face
	face[16].vert[0].vertIndex = 3;	 face[17].vert[3].vertIndex = 17;
	face[16].vert[1].vertIndex = 10; face[17].vert[2].vertIndex = 16;
	face[16].vert[2].vertIndex = 14; face[17].vert[1].vertIndex = 18;
	face[16].vert[3].vertIndex = 7;	 face[17].vert[0].vertIndex = 19;

}

void Mesh::DrawWireframe()
{
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	for (int f = 0; f < numFaces; f++)
	{
		glBegin(GL_POLYGON);
		for (int v = 0; v < face[f].nVerts; v++)
		{
			int		iv = face[f].vert[v].vertIndex;

			glVertex3f(pt[iv].x, pt[iv].y, pt[iv].z);
		}
		glEnd();
	}
}

void Mesh::DrawColor()
{
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	for (int f = 0; f < numFaces; f++)
	{
		glBegin(GL_POLYGON);
		for (int v = 0; v < face[f].nVerts; v++)
		{
			int		iv = face[f].vert[v].vertIndex;
			int		ic = face[f].vert[v].colorIndex;

			ic = ic % COLORNUM;

			glColor3f(ColorArr[ic][0], ColorArr[ic][1], ColorArr[ic][2]);
			glVertex3f(pt[iv].x, pt[iv].y, pt[iv].z);
		}
		glEnd();
	}
}

void Mesh::SetColor(int colorIdx) {
	for (int f = 0; f < numFaces; f++)
	{
		for (int v = 0; v < face[f].nVerts; v++)
		{
			face[f].vert[v].colorIndex = colorIdx;
		}
	}

}